package com.phpxiu.app.view;

import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.widget.Toast;

import com.crashlytics.android.Crashlytics;
import com.facebook.CallbackManager;
import com.facebook.FacebookCallback;
import com.facebook.FacebookException;
import com.facebook.Profile;
import com.facebook.login.LoginManager;
import com.facebook.login.LoginResult;
import com.google.android.gms.auth.api.Auth;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.auth.api.signin.GoogleSignInResult;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.gson.Gson;
import com.google.gson.JsonParseException;
import com.phpxiu.app.kkylive.KKYApp;
import com.phpxiu.app.kkylive.R;
import com.phpxiu.app.model.response.InstUserData;
import com.phpxiu.app.okhttp.OKHttp;
import com.phpxiu.app.supports.qq.QQLoginInfo;
import com.phpxiu.app.supports.qq.QQUserInfo;
import com.phpxiu.app.supports.sina.AccessTokenKeeper;
import com.phpxiu.app.supports.sina.User;
import com.phpxiu.app.supports.sina.UsersAPI;
import com.phpxiu.app.utils.KKYUtil;
import com.sina.weibo.sdk.auth.AuthInfo;
import com.sina.weibo.sdk.auth.Oauth2AccessToken;
import com.sina.weibo.sdk.auth.WeiboAuthListener;
import com.sina.weibo.sdk.auth.sso.SsoHandler;
import com.sina.weibo.sdk.exception.WeiboException;
import com.sina.weibo.sdk.net.RequestListener;
import com.sina.weibo.sdk.utils.LogUtil;
import com.tencent.connect.UserInfo;
import com.tencent.connect.common.Constants;
import com.tencent.mm.sdk.modelmsg.SendAuth;
import com.tencent.mm.sdk.openapi.IWXAPI;
import com.tencent.tauth.IUiListener;
import com.tencent.tauth.Tencent;
import com.tencent.tauth.UiError;
import com.twitter.sdk.android.Twitter;
import com.twitter.sdk.android.core.Callback;
import com.twitter.sdk.android.core.Result;
import com.twitter.sdk.android.core.TwitterApiClient;
import com.twitter.sdk.android.core.TwitterAuthConfig;
import com.twitter.sdk.android.core.TwitterCore;
import com.twitter.sdk.android.core.TwitterException;
import com.twitter.sdk.android.core.TwitterSession;
import com.twitter.sdk.android.core.identity.TwitterLoginButton;
import com.twitter.sdk.android.tweetcomposer.TweetComposer;
import com.twitter.sdk.android.tweetui.TweetUi;

import java.util.Arrays;

import io.fabric.sdk.android.Fabric;
import retrofit2.Call;


/**
 * @file
 * @brief 基本登录封装
 * @author 吴金洲
 * @note 基本登录封装，封装了第三方登录的一些实现逻辑
 *
 */
public abstract class BaseLogin extends UIBase implements WeiboAuthListener,GoogleApiClient.OnConnectionFailedListener{
    public final static String TAG="BaseLogin";
    public final static String LOGIN_ACTION="kky_login_action";
    public final static String LOG_OUT="log_out";//主动退出登录
    public final static String FORCE_LOG_OUT="force_log_out";//强制被动退出登录
    protected final static String WB="weibo";//新浪微博登录方式
    protected final static String WX="weixin";//微信登录方式
    protected final static String QQ="qq";//QQ登录方式
    protected final static String FB="facebook";//Facebook登录方式
    protected final static String TWITTER="twitter";//Twitter登录方式
    protected final static String INST="inst";//Instagram登录方式
    protected final static String GOOGLE="google";//Google+登录方式

    protected final static int INST_OAUTH_REQUEST_CODE=0x1;
    protected final static int GOOGLE_OAUTH_REQUEST_CODE=0x2;
    protected final static int ACCOUNT_LOGIN_REQUEST_CODE=0x3;

    //新浪登录分享配置
    public final static String SINA_APP_KEY="100900920";
    private static final String SINA_REDIRECT = "https://api.weibo.com/oauth2/default.html";//回调页，对用户不可见
    private static final String SINA_SCOPE ="email,direct_messages_read,direct_messages_write,friendships_groups_read,friendships_groups_write,statuses_to_me_read,follow_app_official_microblog," + "invitation_write";

    //QQ登录分享
    public final static String QQ_APP_ID="1105464281";

    public final static String WX_APP_ID="wx4abd1927d329a7e3";

    public final static String WX_APP_SECRET="abfc69260d7f35a2bee554b3c8bad137";

    //Twitter配置
    private final static String T_KEY="ZQSqKvZ2DfppuWSaczSLK1v80";
    private final static String T_SECRET="j7X6tbMHPqaNKpV3afKzjtJ2YPBZYBvGN5cDDvv1m6BvQTrrNe";
    public final static TwitterAuthConfig T_CONFIG=new TwitterAuthConfig(T_KEY,T_SECRET);//twitter授权配置

    private final static Gson gson=new Gson();
    //新浪
    private AuthInfo sinaAuthInfo;
    /** 封装了 "access_token"，"expires_in"，"refresh_token"，并提供了他们的管理功能  */
    private Oauth2AccessToken sinaAccessToken;
    /** 注意：SsoHandler 仅当 SDK 支持 SSO 时有效 */
    private SsoHandler sinaSsoHandler;
    private UsersAPI sinaUsersAPI;
    //微信
    private static IWXAPI WXApi;
    //QQ
    public static Tencent mQQ;
    private UserInfo mQQUserInfo;

    /**
     * facebook登录回调管理
     */
    private CallbackManager FBManager;

    /**
     * twitter登录按钮
     */
    private TwitterLoginButton twitterLogin;


    private GoogleApiClient googleClient;//google客户端实例

    protected boolean isLoginPro=false;//true正在处理登录，其它登录方式不可点击

    private boolean isLoginSina=false;//新浪登录

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        init();
    }

    private void init(){
        sinaAuthInfo = new AuthInfo(this,SINA_APP_KEY,SINA_REDIRECT,SINA_SCOPE);
        sinaSsoHandler = new SsoHandler(BaseLogin.this, sinaAuthInfo);
        sinaAccessToken = AccessTokenKeeper.readAccessToken(this);
        if (sinaAccessToken.isSessionValid()) {
            sinaUsersAPI = new UsersAPI(this,SINA_APP_KEY, sinaAccessToken);
        }else{
            //登录
        }
        WXApi= KKYApp.mWeiXinAPI;
        if(mQQ==null){
            mQQ = KKYApp.getInstance().mQQ;
        }
        initFacebook();
        initTwitter();
        //initGoogle();//注解掉不用google相关功能
        String action=getIntent().getStringExtra(LOGIN_ACTION);
        if(LOG_OUT.equals(action)){
            sendBroadcast(new Intent(com.phpxiu.app.config.Constants.BD_LOG_OUT));
        }else if(FORCE_LOG_OUT.equals(action)){
            sendBroadcast(new Intent(com.phpxiu.app.config.Constants.BD_FORCE_LOG_OUT));
            Toast.makeText(this,"强制登出",Toast.LENGTH_LONG).show();
        }
    }

    /**
     * 初始化Facebook
     */
    final private void initFacebook(){
        FBManager = CallbackManager.Factory.create();
        LoginManager.getInstance().registerCallback(FBManager,new FacebookCallback<LoginResult>() {
            @Override
            public void onSuccess(LoginResult loginResult) {
                final Profile p = Profile.getCurrentProfile();
                if (p != null) {//已登录
                    login(FB,p.getId(),p.getName());
                    KKYUtil.log("FaceBook Login" + p.getId() + "@" + p.getName());
                }else{
                    loginErr(getString(R.string.login_failed));
                }
            }

            @Override
            public void onCancel() {
                loginComplete();
            }

            @Override
            public void onError(FacebookException e) {
                loginErr(getString(R.string.login_failed));
                e.printStackTrace();
            }
        });
    }

    /**
     * 初始化Twitter
     */
    final private void initTwitter(){
        twitterLogin =new TwitterLoginButton(this);
        Fabric.with(this, new Twitter(T_CONFIG));
        Fabric.with(this, new TwitterCore(T_CONFIG), new TweetUi());
        Fabric.with(this, new TwitterCore(T_CONFIG), new TweetComposer(), new Crashlytics());
        twitterLogin.setCallback(new Callback<TwitterSession>() {
            @Override
            public void success(Result<TwitterSession> result) {
                TwitterApiClient client= TwitterCore.getInstance().getApiClient();
                Call<com.twitter.sdk.android.core.models.User> call=client.getAccountService().verifyCredentials(false,false);
                call.enqueue(new Callback<com.twitter.sdk.android.core.models.User>() {
                    @Override
                    public void success(Result<com.twitter.sdk.android.core.models.User> userResult) {
                        final String id=String.valueOf(userResult.data.getId());
                        final String name=userResult.data.name;
                        login(TWITTER,id,name);
                    }

                    @Override
                    public void failure(TwitterException e) {
                        e.printStackTrace();
                        loginErr(getString(R.string.login_failed));
                        //Twitter获取用户信息失败
                    }
                });
            }
            @Override
            public void failure(TwitterException e) {
                //Twitter授权失败
                loginErr(getString(R.string.login_failed));
            }
        });
    }

    /**
     * 初始化Google功能
     */
    final private void initGoogle(){
        GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestEmail()
                .build();
        googleClient = new GoogleApiClient.Builder(this)
                .enableAutoManage(this, this)
                .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
                .build();
        isLoginSina=false;
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connection) {
        loginErr(getString(R.string.login_google_disconnected));
    }

    /**
     * FaceBook登录
     * @see //https://developers.facebook.com/docs/facebook-login/android/
     */
    final protected void loginFaceBook(){
        if(isLoginPro){
            return;
        }
        LoginManager.getInstance().logInWithReadPermissions(this, Arrays.asList("public_profile"));
        isLoginSina=false;
        loginStart();
    }

    final protected void loginTwitter(){
        if(isLoginPro){
            return;
        }
        if(twitterLogin!=null){
           loginStart();
           twitterLogin.performClick();
           isLoginSina=false;
        }
    }

    /**
     * Instagram登录
     */
    final protected void loginInst(){
        if(isLoginPro){
            return;
        }
        Intent inst=new Intent(this,InstOauthWeb.class);
        startActivityForResult(inst,INST_OAUTH_REQUEST_CODE);
        isLoginSina=false;
        loginStart();
    }

    /**
     * google+登录
     */
    final protected void loginGooglePlus(){
        if(isLoginPro){
            return;
        }
        Intent google = Auth.GoogleSignInApi.getSignInIntent(googleClient);
        startActivityForResult(google,GOOGLE_OAUTH_REQUEST_CODE);
        isLoginSina=false;
        loginStart();
    }


    /**
     * 新浪登录
     */
    protected void loginSina(){
        if(isLoginPro){
            return;
        }
        if(!sinaSsoHandler.isWeiboAppInstalled()){
            loginErr(getString(R.string.login_sina_not_install));
            return;
        }
        sinaSsoHandler.authorize(this);
        isLoginSina=true;
        loginStart();
    }

    /**
     * 微信登录
     */
    protected void loginWX(){
        if(isLoginPro){
            return;
        }
        if(!WXApi.isWXAppInstalled()){
            loginErr(getString(R.string.login_wechat_not_install));
            return;
        }
        final SendAuth.Req req = new SendAuth.Req();
        req.scope = "snsapi_userinfo";
        req.state = System.currentTimeMillis()+"";//传随机数
        WXApi.sendReq(req);
        isLoginSina=false;
        loginStart();
    }

    /**
     * QQ登录
     */
    protected void loginQQ(){
        if(isLoginPro){
            return;
        }
        mQQ.login(this,"all",QQListener);
        isLoginSina=false;
        loginStart();
    }

    /**
     * 新浪授权完成
     * @param values
     */
    @Override
    public void onComplete(Bundle values) {
        // 从 Bundle 中解析 Token
        sinaAccessToken = Oauth2AccessToken.parseAccessToken(values);
        if (sinaAccessToken.isSessionValid()) {
            long uid = Long.parseLong(sinaAccessToken.getUid());
            if(sinaUsersAPI==null) {
                sinaUsersAPI = new UsersAPI(this,SINA_APP_KEY, sinaAccessToken);
            }
            sinaUsersAPI.show(uid,sinaUserInfoListener);
        } else {
            // 以下几种情况，您会收到 Code：
            // 1. 当您未在平台上注册的应用程序的包名与签名时；
            // 2. 当您注册的应用程序包名与签名不正确时；
            // 3. 当您在平台上注册的包名和签名与您当前测试的应用的包名和签名不匹配时。
            loginErr(getString(R.string.login_failed));
        }
    }

    /**
     * 新浪授权取消
     */
    @Override
    public void onCancel() {
       loginComplete();
    }
    /**
     * 新浪授权异常
     */
    @Override
    public void onWeiboException(WeiboException e) {
        loginErr(getString(R.string.login_failed));
    }

    /**
     * 新浪授权OpenAPI回调接口。
     */
    private RequestListener sinaUserInfoListener = new RequestListener() {
        @Override
        public void onComplete(String response) {
            if (!TextUtils.isEmpty(response)) {
                LogUtil.i(TAG, response);
                // 调用 User#parse 将JSON串解析成User对象
                User user = User.parse(response);
                if (user != null) {
                    if(KKYUtil.DEBUG) {
                        Toast.makeText(BaseLogin.this, "Sina用户："+user.id+"@"+ user.screen_name,Toast.LENGTH_LONG).show();
                    }
                    login(WB,user.id,user.screen_name);
                } else {
                    loginErr(getString(R.string.login_failed));
                }
            }else{
                loginErr(getString(R.string.login_failed));
            }
        }

        @Override
        public void onWeiboException(WeiboException e) {
            loginErr(getString(R.string.login_failed)+e.getMessage());
        }
    };

    IUiListener QQListener = new IUiListener() {
        @Override
        public void onComplete(Object response) {
            if(response==null){
                loginErr(getString(R.string.login_failed));
                return;
            }
            QQLoginInfo result=null;
            try {
                result = gson.fromJson(response.toString(), QQLoginInfo.class);
            }catch (JsonParseException e){
                loginErr(getString(R.string.login_failed));
            }
            if(result!=null){
                String token=result.getAccess_token();
                String expires=result.getExpires_in();
                String openId=result.getOpenid();
                if (!TextUtils.isEmpty(token) && !TextUtils.isEmpty(expires)
                        && !TextUtils.isEmpty(openId)) {
                    mQQ.setAccessToken(token, expires);
                    mQQ.setOpenId(openId);
                }else {
                    loginErr(getString(R.string.login_failed));
                    return;
                }
                if (mQQ != null && mQQ.isSessionValid()) {
                    mQQUserInfo=new UserInfo(BaseLogin.this,mQQ.getQQToken());
                    mQQUserInfo.getUserInfo(new QQIUiListener(openId));
                }else{
                    loginErr(getString(R.string.login_failed));
                }
            }
        }

        @Override
        public void onError(UiError uiError) {
            loginErr(getString(R.string.login_failed));
        }

        @Override
        public void onCancel() {
            loginComplete();
        }
    };

    class QQIUiListener implements IUiListener {
        private String openId;

        QQIUiListener(String openId) {
            this.openId = openId;
        }

        @Override
        public void onComplete(Object userInfo) {
            if(userInfo==null){
                loginErr(getString(R.string.login_failed));
                return;
            }
            QQUserInfo info=null;
            try {
                info=gson.fromJson(userInfo.toString(),QQUserInfo.class);
            }catch (JsonParseException e){
                loginErr(getString(R.string.login_failed));
            }
            if(info!=null){
                login(QQ,openId,info.getNickname());
            }else{
                loginErr(getString(R.string.login_failed));
            }
        }

        @Override
        public void onError(UiError uiError) {
            loginErr(getString(R.string.login_failed));
        }

        @Override
        public void onCancel() {
            loginComplete();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(requestCode==ACCOUNT_LOGIN_REQUEST_CODE){
            if(resultCode==RESULT_OK){
                finish();
            }
        }else if (requestCode == Constants.REQUEST_LOGIN ||requestCode == Constants.REQUEST_APPBAR) {
            Tencent.onActivityResultData(requestCode, resultCode, data, QQListener);
        }else if(requestCode==INST_OAUTH_REQUEST_CODE){
            if(resultCode==RESULT_OK){
                String result=data.getStringExtra(InstOauthWeb.USER_INFO);
                if(!TextUtils.isEmpty(result)){
                    try {
                        InstUserData userData= OKHttp.GSON.fromJson(result,InstUserData.class);
                        login(INST,userData.getData().getId(),userData.getData().getUsername());
                    }catch (JsonParseException e){
                        loginErr(getString(R.string.login_failed));
                        e.printStackTrace();
                    }catch (NullPointerException e){
                        loginErr(getString(R.string.login_failed));
                        e.printStackTrace();
                    }
                }else{
                    loginErr(getString(R.string.login_failed));
                }
            }else{
                loginComplete();
            }
        }else if(requestCode == GOOGLE_OAUTH_REQUEST_CODE){
            if(resultCode==RESULT_OK){
                GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
                if (result.isSuccess()) {
                    GoogleSignInAccount acct = result.getSignInAccount();
                    login(GOOGLE,acct.getId(),acct.getDisplayName());
                }else{
                    loginErr(getString(R.string.login_failed));
                }
            }else{
                loginComplete();
            }
        }else if(requestCode==T_CONFIG.getRequestCode()){
            if(resultCode==RESULT_OK){
                twitterLogin.onActivityResult(requestCode, resultCode, data);
            }else{
                loginComplete();
            }

        }else{
            if (sinaSsoHandler != null&&isLoginSina) {
                sinaSsoHandler.authorizeCallBack(requestCode, resultCode, data);
            }else{
                FBManager.onActivityResult(requestCode, resultCode, data);
            }
        }
    }

    @Override
    public void onForceLogOut() {
        //TODO NOTHING
    }

    @Override
    public void onLogOut() {
        //TODO NOTHING
    }

    @Override
    public void finish() {
        super.finish();
    }

    /**
     * 登录开始，显示进度条
     */
    protected void loginStart(){
        isLoginPro=true;
    }

    /**
     * 登录失败,提示原因，隐藏进度条
     * @param msg 失败提示
     */
    protected  void loginErr(String msg){
        isLoginPro=false;
    }

    /**
     * 登录过程(正常或异常)结束，关闭进度
     */
    protected  void loginComplete(){
        isLoginPro=false;
    }

    /**
     * 本地登录
     * @param type 登录类型
     * @param uid 平台用户id
     * @param nickName 平台用户昵称
     */
    protected abstract void login(String type,String uid,String nickName);

}
